#ifndef DLM_COMM_H
#define DLM_COMM_H

#include <map>
#include <pthread.h>
#include "Response.h"
#include "Request.h"


/*
 * Communication module class
 */
class DlmComm
{
	public:
		/*
		 * ctor. dlm_fd is the read-end of main DLM pipe
		 */
		DlmComm(int dlm_fd);
		
		/*
		 * dtor.
		 */		
		~DlmComm();
		
		/*
		 * registers client in communication module
		 * client_pid	- pid of the client process
		 * client_fd	- fd which should be used to write responses for the client
		 * 
		 * returns true if client registration was succesful, otherwise false
		 */
		bool clientRegister(pid_t client_pid, int client_fd);
		
		/*
		 * unregisters client from communication module
		 * client_pid	- pid of the client process that should be unregistered
		 */
		void clientUnregister(pid_t client_pid);
		
		/*
		 * checks if client is registerd in the module
		 * client_pid	- pid of the client process
		 * 
		 * returns 		- true if client is registered, otherwise false
		 */
		bool isClientRegistered(pid_t client_pid) const;
		
		
		/*
		 * Receives request from any client. Blocks if there is no request.
		 * 
		 * returns		- pointer to the allocated request structure ( MUST BE DEALLOCATED AFTER USE WITH delete )
		 */		
		Request* receiveRequest(); // należy pamiętać o usunięciu obiektu poprzez delete
		
		/*
		 * sends response to the client
		 * client_pid	- pid of the client process the response is for
		 * code			- response code to be sent
		 * 
		 * returns 		- true if sending response was succesful, false otherwise
		 */		
		bool sendResponse(pid_t client_pid, ResponseCode code);
		
	private:
		typedef std::map<pid_t, int> Clients;
		
		// mutex used to keep clients map consistent
		mutable pthread_mutex_t mutex_;
		
		// read - end of dlm pipe
		int dlmFd_;
				
		Clients clients_;
		
		// send data size bytes from data to client_pid
		bool send(int client_pid, const void *data, unsigned int data_size);
			
		// receive at most buffer_len bytes from client_pid and store them in buffer
		bool receive(char *buffer, unsigned int buffer_len);
		
		
		template<typename R> Request* createRequest(char code);
};

#endif
